package top.fwpsl.util;

import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * 基于Redis的分布式锁
 *
 * @auther: 风戏fw
 * @date: 2020/11/23
 */
public class RedisDistributedLockTool {

    /**
     * 加锁成功状态
     */
    private static final String LOCK_SUCCESS = "OK";

    /**
     * 只在键不存在时，才对键进行设置操作 (用于保证唯一性)
     */
    private static final String SET_IF_NOT_EXIST = "NX";

    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 释放锁成功状态
     */
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 尝试获取分布式锁
     *
     * @param jedis      Redis客户端
     * @param lockKey    锁
     * @param requestId  请求标识 (保证加锁和解锁的是相同的requestId)
     * @param expires    超期时间(单位： 毫秒)
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expires) {
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expires);

        return LOCK_SUCCESS.equals(result);
    }

    /**
     * 释放分布式锁
     *
     * @param jedis     Redis客户端
     * @param lockKey   锁
     * @param requestId 请求标识 (保证加锁和解锁的是相同的requestId)
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        return RELEASE_SUCCESS.equals(result);
    }
}
